package org.kevinth.mail;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import org.tulkas.util.FileUtil;

/**
 * @author <a href="mailto:tulkas.web@gmail.com">Tulkas</a>
 *
 */
public class EmailFilter {
	private static Connection conn;

	private static PreparedStatement stmtChkMail;

	private static PreparedStatement stmtUpdateMail;

	private static PreparedStatement stmtInsertDomain;

	private static int currentId = 0;

	private static int batchSize = 1000;

	private static Map<String, Integer> domains = new HashMap<String, Integer>();

	private static PrintWriter writer = null;

	private static int loadPosition() {
		try {
			FileReader fr = new FileReader("position.txt");
			String str = FileUtil.readString(fr);
			fr.close();
			return Integer.parseInt(str);
		} catch (Exception e) {
			return 0;
		}
	}

	private static void savePosition(int value) throws Exception {
		FileWriter fw = new FileWriter("position.txt");
		PrintWriter w = new PrintWriter(fw);
		w.write(String.valueOf(value));
		w.close();
	}

	private static void refreshConn() throws Exception {
		conn = DriverManager
				.getConnection("jdbc:MySQL://D-SHC-00425544:3306/cn_email_repo?user=root&password=admin&useUnicode=true&characterEncoding=utf8");
		stmtChkMail = conn
				.prepareStatement("select id,email from email where id>? limit "
						+ batchSize);
		stmtUpdateMail = conn
				.prepareStatement("update email set domain_id=? where id=?");
		stmtInsertDomain = conn.prepareStatement(
				"insert into domain(domain) values (?)",
				Statement.RETURN_GENERATED_KEYS);
	}

	private static void closeConns() throws Exception {
		if (stmtChkMail != null)
			stmtChkMail.close();
		if (stmtUpdateMail != null)
			stmtUpdateMail.close();
		if (stmtInsertDomain != null)
			stmtInsertDomain.close();

		if (conn != null)
			conn.close();
	}

	private static void output(String str) {
		System.out.println(str);
		writer.println(str);
	}

	private static Integer getDomainId(String domain) {
		Integer ret = domains.get(domain);
		if (ret == null) {
			int success = 0;
			try {
				stmtInsertDomain.setString(1, domain);
				success = stmtInsertDomain.executeUpdate();
			} catch (SQLException e) {
				output("ERROR: " + e.getMessage());
			}

			if (success > 0) {
				try {
					ResultSet rs = stmtInsertDomain.getGeneratedKeys();
					if (rs.next()) {
						ret = rs.getInt(1);
					}
					domains.put(domain, ret);
					output("domain: " + domain + " - " + ret);
				} catch (SQLException e) {
					output("ERROR: " + e.getMessage());
				}
			}
		}

		return ret;
	}

	private static boolean checkBatch() {
		boolean ret = false;
		try {
			stmtChkMail.setInt(1, currentId);
			ResultSet rs = stmtChkMail.executeQuery();
			while (rs.next()) {
				ret = true;
				int id = rs.getInt("id");
				if (currentId < id)
					currentId = id;
				String email = rs.getString("email");
				String domain = EmailChecker.getDomain(email);
				Integer dId = getDomainId(domain);
				if (dId != null) {
					stmtUpdateMail.setInt(1, dId);
					stmtUpdateMail.setInt(2, id);
					stmtUpdateMail.execute();
				}
			}
		} catch (SQLException e) {
			output("ERROR: " + e.getMessage());
		}
		return ret;
	}

	public static void main(String[] args) throws Exception {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			writer = new PrintWriter(new FileWriter("output.txt"));

			currentId = loadPosition();
			output("Start User Id :" + currentId);
			boolean ret = true;

			while (ret) {
				refreshConn();
				ret = checkBatch();
				savePosition(currentId);
				output("Finish batch, current id:" + currentId);
				writer.flush();
				closeConns();
			}

		} finally {
			closeConns();
		}
	}
}
